package com.cxh.androidmedia.render_new.filter;

import android.opengl.GLES30;
import android.opengl.Matrix;

import com.cxh.androidmedia.base.AMApp;
import com.cxh.androidmedia.render_old.bean.BeautyParams;
import com.cxh.androidmedia.utils.BitsUtil;
import com.cxh.androidmedia.utils.FileUtil;
import com.cxh.androidmedia.utils.OpenGLUtils;

/**
 * Created by Cxh
 * Time : 2020-09-17  23:24
 * Desc :
 */
public class TextureFilterPreviewFilter extends BaseGLBeautyFilter {

    protected final float[] mProjectionMatrix = new float[16];

    private int mGLProgram;
    private int mMatrixHandler;
    private int mVertexHandler;
    private int mTextureHandler;

    private int mCurrentFilter;
    private int mCurrentAngle = 0;

    private float[] vertexArray = new float[]{
            -1, 1, 0,
            1, 1, 0,
            1, -1, 0,
            -1, -1, 0
    };

    private float[] texCoordsArray = new float[]{
            0, 1,
            1, 1,
            1, 0,
            0, 0
    };

    private static short[] drawIndex = {
            0, 1, 2,
            0, 2, 3
    };

    public TextureFilterPreviewFilter(int width, int height) {
        super(width, height);

        mGLProgram = GLES30.glCreateProgram();

        String vertexCode = FileUtil.readShaderFromAssets(AMApp.get(), "glsl/render2/render_vertex_image.glsl");
        String fragmentCode = FileUtil.readShaderFromAssets(AMApp.get(), "glsl/render2/render_fragment_image.glsl");
        int vertexShader = OpenGLUtils.loadShader(GLES30.GL_VERTEX_SHADER, vertexCode);
        OpenGLUtils.checkShaderCompileError(vertexShader, "vertexShader");

        int fragShader = OpenGLUtils.loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentCode);
        OpenGLUtils.checkShaderCompileError(fragShader, "fragShader");

        GLES30.glAttachShader(mGLProgram, vertexShader);
        GLES30.glAttachShader(mGLProgram, fragShader);
        GLES30.glLinkProgram(mGLProgram);
        GLES30.glValidateProgram(mGLProgram);
        OpenGLUtils.printLog(mGLProgram);

        GLES30.glDeleteShader(vertexShader);
        GLES30.glDeleteShader(fragShader);

        // 竖屏。需要设置的就是上下
        Matrix.orthoM(mProjectionMatrix, 0, -1, 1f, -1, 1, -1.f, 1f);
    }

    @Override
    public int draw(int textureId, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
        GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);

        // 变换矩阵
        GLES30.glUseProgram(mGLProgram);
        mMatrixHandler = GLES30.glGetUniformLocation(mGLProgram, "uMatrix");
        float[] combineMatrix = setRotateM(mProjectionMatrix, mCurrentAngle);
        GLES30.glUniformMatrix4fv(mMatrixHandler, 1, false, combineMatrix, 0);

        // 常量
        OpenGLUtils.setUnifrom1i(mGLProgram, "mFilterType", mCurrentFilter);
        OpenGLUtils.setUnifrom1f(mGLProgram, "mTexWidth", width);
        OpenGLUtils.setUnifrom1f(mGLProgram, "mTexHeight", height);

        mVertexHandler = GLES30.glGetAttribLocation(mGLProgram, "vertexPosition");
        GLES30.glVertexAttribPointer(mVertexHandler, 3, GLES30.GL_FLOAT, false, 0, BitsUtil.arraysToBuffer(vertexArray));
        GLES30.glEnableVertexAttribArray(mVertexHandler);

        mTextureHandler = GLES30.glGetAttribLocation(mGLProgram, "textureCoord");
        GLES30.glVertexAttribPointer(mTextureHandler, 2, GLES30.GL_FLOAT, false, 0, BitsUtil.arraysToBuffer(texCoordsArray));
        GLES30.glEnableVertexAttribArray(mTextureHandler);

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, drawIndex.length, GLES30.GL_UNSIGNED_SHORT, BitsUtil.arraysToBuffer(drawIndex));

        return 0;
    }

    @Override
    public void release() {
        super.release();
        GLES30.glDeleteProgram(mGLProgram);
    }

    private float[] setRotateM(float[] matrix, int rotateAngle) {
        float[] viewMatrix = new float[16];
        float[] targetMatrix = new float[16];
        Matrix.setIdentityM(viewMatrix, 0);
        Matrix.setRotateM(viewMatrix, 0, rotateAngle, 0f, 0f, 1f);
        Matrix.multiplyMM(targetMatrix, 0, viewMatrix, 0, matrix, 0);
        return targetMatrix;
    }

    public void setCurrentFilter(int currentFilter) {
        this.mCurrentFilter = currentFilter;
    }

    public void setCurrentFilter(String filterType) {
        switch (filterType) {
            case BeautyParams.FILTER_TYPE_DEFAULT:
                mCurrentFilter = 0;
                break;
            case BeautyParams.FILTER_TYPE_NO_COLOR:
                mCurrentFilter = 1;
                break;
            case BeautyParams.FILTER_TYPE_WARM:
                mCurrentFilter = 2;
                break;
            case BeautyParams.FILTER_TYPE_COLD:
                mCurrentFilter = 3;
                break;
            case BeautyParams.FILTER_TYPE_REVERSE:
                mCurrentFilter = 4;
                break;
            case BeautyParams.FILTER_TYPE_MOSAIC:
                mCurrentFilter = 6;
                break;
            case BeautyParams.FILTER_TYPE_MOSAIC_CIRCLE:
                mCurrentFilter = 7;
                break;
            case BeautyParams.FILTER_TYPE_ART:
                mCurrentFilter = 8;
                break;
            case BeautyParams.FILTER_TYPE_AVG_BLUR:
                mCurrentFilter = 9;
                break;
            case BeautyParams.FILTER_TYPE_GAUSS_BLUR:
                mCurrentFilter = 10;
                break;
            case BeautyParams.FILTER_TYPE_RELIEF:
                mCurrentFilter = 11;
                break;
            case BeautyParams.FILTER_TYPE_STRONG:
                mCurrentFilter = 12;
                break;
            case BeautyParams.FILTER_TYPE_NINE:
                mCurrentFilter = 13;
                break;
            case BeautyParams.FILTER_TYPE_XXX:
                mCurrentFilter = 14;
                break;
        }
    }
}
